import static org.junit.Assert.*;

import java.util.ArrayList;

import javax.swing.JLabel;
import javax.swing.JLayeredPane;

import org.junit.Test;

/**
 * This class contains some JUnit tests that test the reliability of our code.
 * 
 * @author GT Five-O
 * @version v1.0b
 */
public class MuleTest {

    private Player[] players;
    private Store store;
    private GameScreen board;

    public void SetUp() {
        gameConfigurationScreen gameInit = new gameConfigurationScreen();
        gameInit.setVisible(true);

        boolean flag = true;
        while (flag) {
            if (!gameInit.isVisible()) {
                flag = gameInit.isNotFinished();
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        ArrayList<String[]> playerData = gameInit.getPlayerData();

        players = new Player[playerData.size()];

        for (int i = 0; i < playerData.size(); i++) {
            String name = playerData.get(i)[0];
            String race = playerData.get(i)[1];
            String color = playerData.get(i)[2];
            String level = playerData.get(i)[3];
            players[i] = new Player(name, race, color, i, level);
            players[i].setScore();
        }
        board = new GameScreen(players, gameInit.getMapSelected());
        // board.setVisible(true);
        board.setCurrent(players[0]);

        store = new Store(board);
        gameInit.dispose();
    }

    @Test
    public void validateUniquePlayerColors() {

        SetUp();

        int red = 0, black = 0, green = 0, yellow = 0;
        boolean r = false, b = false, g = false, y = false;

        for (Player p : players) {
            String color = p.getPlayerColor();
            if (color.equals("Red")) {
                red++;
            } else if (color.equals("Black")) {
                black++;
            } else if (color.equals("Green")) {
                green++;
            } else if (color.equals("Yellow")) {
                yellow++;
            }
        }

        if (red < 2) {
            r = true;
        }
        if (black < 2) {
            b = true;
        }
        if (green < 2) {
            g = true;
        }
        if (yellow < 2) {
            y = true;
        }

        assertEquals(true, r);
        assertEquals(true, b);
        assertEquals(true, g);
        assertEquals(true, y);

    }

    @Test
    public void StoreSellsInventoryChecktest() { // Gautham's JUnit Test Case

        SetUp();

        int foodCountInitial = 8;
        int oreCountInitial = 0;
        int energyCountInitial = 4;

        int storeEnergy = 16;
        int storeFood = 16;
        int storeOre = 0;

        // Check for initial player quantities
        assertEquals(foodCountInitial, players[0].getFood());
        assertEquals(oreCountInitial, players[0].getOre());
        assertEquals(energyCountInitial, players[0].getEnergy());

        // Check initial store quantities
        assertEquals(storeEnergy, store.getEnergy());
        assertEquals(storeFood, store.getFood());
        assertEquals(storeOre, store.getOre());

        store.sellFood();
        store.sellEnergy();
        store.sellOre();

        // Check if player inventory is affected
        assertEquals(foodCountInitial + 1, players[0].getFood());
        assertEquals(oreCountInitial, players[0].getOre()); // since store and
                                                            // player both dont
                                                            // have ores value
                                                            // remains the same
        assertEquals(energyCountInitial + 1, players[0].getEnergy());

        // Check if store inventory is affected
        assertEquals(storeEnergy - 1, store.getEnergy());
        assertEquals(storeFood - 1, store.getFood()); // store doesn't have
                                                      // energy to sell
        assertEquals(storeOre, store.getOre());

    }

    @Test
    public void PlayerSellsInventoryChecktest() { // Alyshaz's JUnit Test Case
        SetUp();

        int foodCountInitial = 8;
        int oreCountInitial = 0;
        int energyCountInitial = 4;

        int storeEnergy = 16;
        int storeFood = 16;
        int storeOre = 0;

        store.buyFood();
        store.buyEnergy();
        store.buyOre();

        // Check if player inventory is affected
        assertEquals(foodCountInitial - 1, players[0].getFood());
        assertEquals(oreCountInitial, players[0].getOre()); // since store and
                                                            // player both don't
                                                            // have ores value
                                                            // remains the same
        assertEquals(energyCountInitial - 1, players[0].getEnergy());

        assertEquals(null, players[0].removeOre()); // returns null if no
                                                    // available ores

        // Check if store inventory is affected
        assertEquals(storeEnergy + 1, store.getEnergy());
        assertEquals(storeFood + 1, store.getFood()); // store doesn't have
                                                      // energy to sell
        assertEquals(storeOre, store.getOre());

    }

    @Test
    public void checkPlayerTimer() { // Avdeep's JUnit
        SetUp();

        PlayerTimer timer = new PlayerTimer(); // instance of timer
        int food = 3; // hard setting the parameters
        int rec = 1;
        assertEquals(50000L, (long) timer.getPlayerTime(food, rec)); // checking
                                                                     // to see
                                                                     // if the
                                                                     // conditionals
                                                                     // return
                                                                     // the
                                                                     // right
                                                                     // value
        food = 0;
        assertEquals(5000L, (long) timer.getPlayerTime(food, rec));
        food = -5;
        assertEquals(30000L, (long) timer.getPlayerTime(food, rec));
        assertEquals((long) timer.getRoundLimit(),
                (long) timer.getPlayerTime(food, rec));
        timer.setRoundTime(15L);
        assertEquals(true, timer.checkRound());

    }

    @Test
    public void mulePlayerCountTest() { // Taufiq's JUnit Test Case
        SetUp();
        Mule m = new Mule();
        players[0].addMule(m);
        assertEquals("" + 1, players[0].getMuleCount());
        players[0].removeMule(m);
        assertEquals("" + 0, players[0].getMuleCount());
    }

    @Test
    public void muleIconTest() { // Taufiq's JUnit Test Case
        Property p = new Property();
        JLayeredPane mainPane = new JLayeredPane();
        IDAssociator temp = new IDAssociator(p.getPropertyID(), 5, 15, 50, 50,
                mainPane, true);
        temp.setJLabelIcon("Images/MuleIcons/food.png");
        assertEquals(1, mainPane.getComponents().length);
        assertEquals(false, ((JLabel) temp.getData()).getIcon() == null);
        assertEquals(true, ((JLabel) temp.getData()).isOpaque());
        temp.removeData();
        assertEquals(0, mainPane.getComponents().length);
    }

    /**
     * Test is responsible for creating 3 generic human players at three
     * different levels and checking if they were initialized correctly
     * 
     */
    @Test
    public void difficultyTest() {

        // creating 3 new players
        players = new Player[3];
        players[0] = new Player("name", "Human", "Red", 0, "Beginner");
        players[1] = new Player("name", "Human", "Red", 0, "Intermediate");
        players[2] = new Player("name", "Human", "Red", 0, "Expert");

        // checking if each player has been initialed correctly
        assertEquals(players[0].getFood(), 8);
        assertEquals(players[1].getFood(), 4);
        assertEquals(players[2].getFood(), 2);

        assertEquals(players[0].getEnergy(), 4);
        assertEquals(players[1].getEnergy(), 2);
        assertEquals(players[2].getEnergy(), 2);
    }

    /**
     * Checks to see if the game compares the players correctly and calculates
     * the scores correctly
     */
    @Test
    public void testScores() {
        // creates 3 players at different levels
        players = new Player[3];
        players[0] = new Player("name", "Human", "Red", 0, "Beginner");
        players[1] = new Player("name", "Human", "Red", 0, "Intermediate");
        players[2] = new Player("name", "Human", "Red", 0, "Expert");

        // makes sure each player was initiazed with the correct score
        assertEquals(players[0].getScore(), 12);
        assertEquals(players[1].getScore(), 6);
        assertEquals(players[2].getScore(), 4);

        // checks to see if each combination of pairs were compared correctly
        assertTrue(players[0].compareTo(players[1]) == 1);
        assertTrue(players[1].compareTo(players[2]) == 1);
        assertTrue(players[0].compareTo(players[2]) == 1);

        // player 3's original score
        int player3Score = players[2].getScore();

        for (int i = 0; i < 10; i++) {
            players[2].addFood(new Food());
            players[2].addEnergy(new Energy());
            players[2].addOre(new Ore());
        }

        // checks if the score can properly recalculate, and checks the
        // compareTo method
        assertEquals(player3Score + 30, players[2].getScore());
        assertFalse(players[1].compareTo(players[2]) == 1);
        assertFalse(players[0].compareTo(players[2]) == 1);
    }

    /**
     * Checks to see if mules properly harvest.
     */
    @Test
    public void muleHarvestTest() {

        int orignalResource, originalEnergy;

        // creates a player with an excess of energy
        Player player = new Player("name", "Human", "Red", 0, "Beginner");
        for (int i = 0; i < 50; i++)
            player.addEnergy(new Energy());

        // creates a new mule on a mountain
        Mule temp = new Mule();
        temp.setProperty(new Mountain1());

        // makes the mule an ore type mule and checks to see if it harvested
        // correctly and reduced the energy correctly
        temp.setType("Ore");
        player.addMule(temp);
        orignalResource = player.getOre();
        originalEnergy = player.getEnergy();
        player.updateResources();
        assertEquals(player.getFood(), orignalResource + 8);
        assertEquals(player.getEnergy(), originalEnergy - 1);
        player.removeMule(temp);

        // makes the mule an food type mule and checks to see if it harvested
        // correctly and reduced the energy correctly
        temp.setType("Food");
        player.addMule(temp);
        orignalResource = player.getFood();
        originalEnergy = player.getEnergy();
        player.updateResources();
        assertEquals(player.getFood(), orignalResource + 1);
        assertEquals(player.getEnergy(), originalEnergy - 1);
        player.removeMule(temp);

        // makes the mule an energy type mule and checks to see if it harvested
        // correctly
        temp.setType("Energy");
        player.addMule(temp);
        orignalResource = player.getEnergy();
        player.updateResources();
        assertEquals(player.getEnergy(), orignalResource);
        player.removeMule(temp);

        // changes the land type to see if the property type correctly impacts
        // the harvest
        temp.setType("Energy");
        temp.setProperty(new Plain());
        player.addMule(temp);
        orignalResource = player.getEnergy();
        player.updateResources();
        assertEquals(player.getEnergy(), orignalResource + 2);
        player.removeMule(temp);

    }

}
